home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1995 March / macformat-022.iso / Shareware City / Developers / src / out-of-phase-102-c / OutOfPhase 1.02 Source / OutOfPhase Folder / ASTUnaryOperator.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-11-23  |  21.5 KB  |  737 lines  |  [TEXT/KAHL]

  1. /* ASTUnaryOperator.c */
  2. /*****************************************************************************/
  3. /*                                                                           */
  4. /*    Out Of Phase:  Digital Music Synthesis on General Purpose Computers    */
  5. /*    Copyright (C) 1994  Thomas R. Lawrence                                 */
  6. /*                                                                           */
  7. /*    This program is free software; you can redistribute it and/or modify   */
  8. /*    it under the terms of the GNU General Public License as published by   */
  9. /*    the Free Software Foundation; either version 2 of the License, or      */
  10. /*    (at your option) any later version.                                    */
  11. /*                                                                           */
  12. /*    This program is distributed in the hope that it will be useful,        */
  13. /*    but WITHOUT ANY WARRANTY; without even the implied warranty of         */
  14. /*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
  15. /*    GNU General Public License for more details.                           */
  16. /*                                                                           */
  17. /*    You should have received a copy of the GNU General Public License      */
  18. /*    along with this program; if not, write to the Free Software            */
  19. /*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
  20. /*                                                                           */
  21. /*    Thomas R. Lawrence can be reached at tomlaw@world.std.com.             */
  22. /*                                                                           */
  23. /*****************************************************************************/
  24.  
  25. #include "MiscInfo.h"
  26. #include "Audit.h"
  27. #include "Debug.h"
  28. #include "Definitions.h"
  29.  
  30. #include "ASTUnaryOperator.h"
  31. #include "ASTExpression.h"
  32. #include "TrashTracker.h"
  33. #include "Memory.h"
  34. #include "PromotableTypeCheck.h"
  35.  
  36.  
  37. struct ASTUnaryOpRec
  38.     {
  39.         UnaryOpType                    Operation;
  40.         ASTExpressionRec*        Argument;
  41.         long                                LineNumber;
  42.     };
  43.  
  44.  
  45. /* create a unary operator node */
  46. ASTUnaryOpRec*    NewUnaryOperator(UnaryOpType WhatOperation,
  47.                                     struct ASTExpressionRec* Argument, struct TrashTrackRec* TrashTracker,
  48.                                     long LineNumber)
  49.     {
  50.         ASTUnaryOpRec*    UnaryOp;
  51.  
  52.         CheckPtrExistence(Argument);
  53.         CheckPtrExistence(TrashTracker);
  54.         UnaryOp = (ASTUnaryOpRec*)AllocTrackedBlock(sizeof(ASTUnaryOpRec),TrashTracker);
  55.         if (UnaryOp == NIL)
  56.             {
  57.                 return NIL;
  58.             }
  59.         SetTag(UnaryOp,"ASTUnaryOpRec");
  60.  
  61.         UnaryOp->LineNumber = LineNumber;
  62.         UnaryOp->Operation = WhatOperation;
  63.         UnaryOp->Argument = Argument;
  64.  
  65.         return UnaryOp;
  66.     }
  67.  
  68.  
  69. /* type check the unary operator node.  this returns eCompileNoError if */
  70. /* everything is ok, and the appropriate type in *ResultingDataType. */
  71. CompileErrors        TypeCheckUnaryOperator(DataTypes* ResultingDataType,
  72.                                     ASTUnaryOpRec* UnaryOperator, long* ErrorLineNumber,
  73.                                     struct TrashTrackRec* TrashTracker)
  74.     {
  75.         CompileErrors    Error;
  76.         DataTypes            ArgumentType;
  77.  
  78.         CheckPtrExistence(UnaryOperator);
  79.         CheckPtrExistence(TrashTracker);
  80.  
  81.         /* check the argument and find out what type it is */
  82.         Error = TypeCheckExpression(&ArgumentType,UnaryOperator->Argument,
  83.             ErrorLineNumber,TrashTracker);
  84.         if (Error != eCompileNoError)
  85.             {
  86.                 return Error;
  87.             }
  88.  
  89.         /* do type checking and promotion; return type determination is deferred... */
  90.         switch (UnaryOperator->Operation)
  91.             {
  92.                 default:
  93.                     EXECUTE(PRERR(ForceAbort,"TypeCheckUnaryOperator:  unknown opcode"));
  94.                     break;
  95.  
  96.                 /* operators which take an integer, single, double, or fixed and */
  97.                 /* return a boolean */
  98.                 case eUnaryTestNegative:
  99.                     /* FALL THROUGH */
  100.  
  101.                 /* operators which take an integer, single, double, or fixed and */
  102.                 /* return an integer */
  103.                 case eUnaryGetSign:
  104.                     /* FALL THROUGH */
  105.  
  106.                 /* operators capable of integer, single, double, fixed arguments */
  107.                 /* which return the same type as the argument */
  108.                 case eUnaryNegation:
  109.                 case eUnaryAbsoluteValue:
  110.                     if (!IsItASequencedScalarType(ArgumentType))
  111.                         {
  112.                             *ErrorLineNumber = UnaryOperator->LineNumber;
  113.                             return eCompileOperandsMustBeSequencedScalar;
  114.                         }
  115.                     break;
  116.  
  117.                 /* operators capable of boolean or integer arguments which */
  118.                 /* return the same type as the argument */
  119.                 case eUnaryNot:
  120.                     if ((ArgumentType != eBoolean) && (ArgumentType != eInteger))
  121.                         {
  122.                             *ErrorLineNumber = UnaryOperator->LineNumber;
  123.                             return eCompileOperandMustBeBooleanOrInteger;
  124.                         }
  125.                     break;
  126.  
  127.                 /* operators capable of double arguments which return doubles */
  128.                 case eUnarySine:
  129.                 case eUnaryCosine:
  130.                 case eUnaryTangent:
  131.                 case eUnaryArcSine:
  132.                 case eUnaryArcCosine:
  133.                 case eUnaryArcTangent:
  134.                 case eUnaryLogarithm:
  135.                 case eUnaryExponentiation:
  136.                 case eUnarySquare:
  137.                 case eUnarySquareRoot:
  138.                     if (!CanRightBeMadeToMatchLeft(eDouble,ArgumentType))
  139.                         {
  140.                             *ErrorLineNumber = UnaryOperator->LineNumber;
  141.                             return eCompileOperandMustBeDouble;
  142.                         }
  143.                     if (MustRightBePromotedToLeft(eDouble,ArgumentType))
  144.                         {
  145.                             ASTExpressionRec*        PromotedOperand;
  146.  
  147.                             /* we must promote the right operand to become the left operand type */
  148.                             PromotedOperand = PromoteTheExpression(ArgumentType/*orig*/,
  149.                                 eDouble/*desired*/,UnaryOperator->Argument,
  150.                                 UnaryOperator->LineNumber,TrashTracker);
  151.                             if (PromotedOperand == NIL)
  152.                                 {
  153.                                     *ErrorLineNumber = UnaryOperator->LineNumber;
  154.                                     return eCompileOutOfMemory;
  155.                                 }
  156.                             UnaryOperator->Argument = PromotedOperand;
  157.                             /* sanity check */
  158.                             Error = TypeCheckExpression(&ArgumentType/*obtain new right type*/,
  159.                                 UnaryOperator->Argument,ErrorLineNumber,TrashTracker);
  160.                             ERROR((Error != eCompileNoError),PRERR(ForceAbort,
  161.                                 "TypeCheckUnaryOperator:  type promotion caused failure"));
  162.                             ERROR(eDouble != ArgumentType,PRERR(ForceAbort,
  163.                                 "TypeCheckUnaryOperator:  after type promotion, types are no"
  164.                                 " longer the same"));
  165.                         }
  166.                     break;
  167.  
  168.                 /* operands which take a boolean, integer, single, double, or fixed */
  169.                 /* and return an integer */
  170.                 case eUnaryCastToInteger:
  171.                     /* FALL THROUGH */
  172.  
  173.                 /* operators which take a boolean, integer, single, double, or fixed */
  174.                 /* and return a single */
  175.                 case eUnaryCastToSingle:
  176.                     /* FALL THROUGH */
  177.  
  178.                 /* operators which take a boolean, integer, single, double, or fixed */
  179.                 /* and return a double */
  180.                 case eUnaryCastToDouble:
  181.                     /* FALL THROUGH */
  182.  
  183.                 /* operators which take a boolean, integer, single, double, or fixed */
  184.                 /* and return a fixed */
  185.                 case eUnaryCastToFixed:
  186.                     /* FALL THROUGH */
  187.  
  188.                 /* operators which take a boolean, integer, single, double, or fixed */
  189.                 /* and return a boolean */
  190.                 case eUnaryCastToBoolean:
  191.                     if (!IsItAScalarType(ArgumentType))
  192.                         {
  193.                             *ErrorLineNumber = UnaryOperator->LineNumber;
  194.                             return eCompileOperandsMustBeScalar;
  195.                         }
  196.                     break;
  197.  
  198.                 /* operators which take an array and return an integer */
  199.                 case eUnaryGetArrayLength:
  200.                     if (!IsItAnIndexedType(ArgumentType))
  201.                         {
  202.                             *ErrorLineNumber = UnaryOperator->LineNumber;
  203.                             return eCompileArrayRequiredForGetLength;
  204.                         }
  205.                     break;
  206.             }
  207.  
  208.         /* figure out the return type */
  209.         switch (UnaryOperator->Operation)
  210.             {
  211.                 default:
  212.                     EXECUTE(PRERR(ForceAbort,"TypeCheckUnaryOperator:  unknown opcode"));
  213.                     break;
  214.  
  215.                 /* operators which take an integer, single, double, or fixed and */
  216.                 /* return a boolean */
  217.                 case eUnaryTestNegative:
  218.                     ERROR(!IsItASequencedScalarType(ArgumentType),PRERR(ForceAbort,
  219.                         "TypeCheckUnaryOperator:  arg should be seq scalar but isn't"));
  220.                     *ResultingDataType = eBoolean;
  221.                     break;
  222.  
  223.                 /* operators which take an integer, single, double, or fixed and */
  224.                 /* return an integer */
  225.                 case eUnaryGetSign:
  226.                     ERROR(!IsItASequencedScalarType(ArgumentType),PRERR(ForceAbort,
  227.                         "TypeCheckUnaryOperator:  arg should be seq scalar but isn't"));
  228.                     *ResultingDataType = eInteger;
  229.                     break;
  230.  
  231.                 /* operators capable of integer, single, double, fixed arguments */
  232.                 /* which return the same type as the argument */
  233.                 case eUnaryNegation:
  234.                 case eUnaryAbsoluteValue:
  235.                     ERROR(!IsItASequencedScalarType(ArgumentType),PRERR(ForceAbort,
  236.                         "TypeCheckUnaryOperator:  arg should be seq scalar but isn't"));
  237.                     *ResultingDataType = ArgumentType;
  238.                     break;
  239.  
  240.                 /* operators capable of boolean or integer arguments which */
  241.                 /* return the same type as the argument */
  242.                 case eUnaryNot:
  243.                     ERROR((ArgumentType != eBoolean) && (ArgumentType != eInteger),
  244.                         PRERR(ForceAbort,"TypeCheckUnaryOperator:  arg should be int or bool"));
  245.                     *ResultingDataType = ArgumentType;
  246.                     break;
  247.  
  248.                 /* operators capable of double arguments which return doubles */
  249.                 case eUnarySine:
  250.                 case eUnaryCosine:
  251.                 case eUnaryTangent:
  252.                 case eUnaryArcSine:
  253.                 case eUnaryArcCosine:
  254.                 case eUnaryArcTangent:
  255.                 case eUnaryLogarithm:
  256.                 case eUnaryExponentiation:
  257.                 case eUnarySquare:
  258.                 case eUnarySquareRoot:
  259.                     ERROR(ArgumentType != eDouble,PRERR(ForceAbort,
  260.                         "TypeCheckUnaryOperator:  arg should be double but isn't"));
  261.                     *ResultingDataType = eDouble;
  262.                     break;
  263.  
  264.                 /* operands which take a boolean, integer, single, double, or fixed */
  265.                 /* and return an integer */
  266.                 case eUnaryCastToInteger:
  267.                     ERROR(!IsItAScalarType(ArgumentType),PRERR(ForceAbort,
  268.                         "TypeCheckUnaryOperator:  arg should be scalar but isn't"));
  269.                     *ResultingDataType = eInteger;
  270.                     break;
  271.  
  272.                 /* operators which take a boolean, integer, single, double, or fixed */
  273.                 /* and return a single */
  274.                 case eUnaryCastToSingle:
  275.                     ERROR(!IsItAScalarType(ArgumentType),PRERR(ForceAbort,
  276.                         "TypeCheckUnaryOperator:  arg should be scalar but isn't"));
  277.                     *ResultingDataType = eFloat;
  278.                     break;
  279.  
  280.                 /* operators which take a boolean, integer, single, double, or fixed */
  281.                 /* and return a double */
  282.                 case eUnaryCastToDouble:
  283.                     ERROR(!IsItAScalarType(ArgumentType),PRERR(ForceAbort,
  284.                         "TypeCheckUnaryOperator:  arg should be scalar but isn't"));
  285.                     *ResultingDataType = eDouble;
  286.                     break;
  287.  
  288.                 /* operators which take a boolean, integer, single, double, or fixed */
  289.                 /* and return a fixed */
  290.                 case eUnaryCastToFixed:
  291.                     ERROR(!IsItAScalarType(ArgumentType),PRERR(ForceAbort,
  292.                         "TypeCheckUnaryOperator:  arg should be scalar but isn't"));
  293.                     *ResultingDataType = eFixed;
  294.                     break;
  295.  
  296.                 /* operators which take a boolean, integer, single, double, or fixed */
  297.                 /* and return a boolean */
  298.                 case eUnaryCastToBoolean:
  299.                     ERROR(!IsItAScalarType(ArgumentType),PRERR(ForceAbort,
  300.                         "TypeCheckUnaryOperator:  arg should be scalar but isn't"));
  301.                     *ResultingDataType = eBoolean;
  302.                     break;
  303.  
  304.                 /* operators which take an array and return an integer */
  305.                 case eUnaryGetArrayLength:
  306.                     ERROR(!IsItAnIndexedType(ArgumentType),PRERR(ForceAbort,
  307.                         "TypeCheckUnaryOperator:  arg should be indexable but isn't"));
  308.                     *ResultingDataType = eInteger;
  309.                     break;
  310.             }
  311.  
  312.         return eCompileNoError;
  313.     }
  314.  
  315.  
  316. /* generate code for a unary operator. returns True if successful, or False if it fails. */
  317. MyBoolean                CodeGenUnaryOperator(struct PcodeRec* FuncCode,
  318.                                     long* StackDepthParam, ASTUnaryOpRec* UnaryOperator)
  319.     {
  320.         long                    StackDepth;
  321.         Pcodes                Opcode;
  322.  
  323.         CheckPtrExistence(FuncCode);
  324.         CheckPtrExistence(UnaryOperator);
  325.         StackDepth = *StackDepthParam;
  326.  
  327.         /* evaluate the argument */
  328.         if (!CodeGenExpression(FuncCode,&StackDepth,UnaryOperator->Argument))
  329.             {
  330.                 return False;
  331.             }
  332.         ERROR(StackDepth != *StackDepthParam + 1,PRERR(ForceAbort,
  333.             "CodeGenUnaryOperator:  stack depth error after evaluating argument"));
  334.  
  335.         /* generate the operation code */
  336.         switch (UnaryOperator->Operation)
  337.             {
  338.                 default:
  339.                     EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator:  bad opcode"));
  340.                     break;
  341.  
  342.                 case eUnaryNegation:
  343.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  344.                         {
  345.                             default:
  346.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryNegation]:  "
  347.                                     "bad type"));
  348.                                 break;
  349.                             case eInteger:
  350.                                 Opcode = epOperationIntegerNegation;
  351.                                 break;
  352.                             case eFloat:
  353.                                 Opcode = epOperationFloatNegation;
  354.                                 break;
  355.                             case eDouble:
  356.                                 Opcode = epOperationDoubleNegation;
  357.                                 break;
  358.                             case eFixed:
  359.                                 Opcode = epOperationFixedNegation;
  360.                                 break;
  361.                         }
  362.                     break;
  363.  
  364.                 case eUnaryNot:
  365.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  366.                         {
  367.                             default:
  368.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryNot]:  "
  369.                                     "bad type"));
  370.                                 break;
  371.                             case eBoolean:
  372.                                 Opcode = epOperationBooleanNot;
  373.                                 break;
  374.                             case eInteger:
  375.                                 Opcode = epOperationIntegerNot;
  376.                                 break;
  377.                         }
  378.                     break;
  379.  
  380.                 case eUnarySine:
  381.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  382.                         {
  383.                             default:
  384.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnarySine]:  "
  385.                                     "bad type"));
  386.                                 break;
  387.                             case eDouble:
  388.                                 Opcode = epOperationDoubleSin;
  389.                                 break;
  390.                         }
  391.                     break;
  392.  
  393.                 case eUnaryCosine:
  394.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  395.                         {
  396.                             default:
  397.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryCosine]:  "
  398.                                     "bad type"));
  399.                                 break;
  400.                             case eDouble:
  401.                                 Opcode = epOperationDoubleCos;
  402.                                 break;
  403.                         }
  404.                     break;
  405.  
  406.                 case eUnaryTangent:
  407.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  408.                         {
  409.                             default:
  410.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryTangent]:  "
  411.                                     "bad type"));
  412.                                 break;
  413.                             case eDouble:
  414.                                 Opcode = epOperationDoubleTan;
  415.                                 break;
  416.                         }
  417.                     break;
  418.  
  419.                 case eUnaryArcSine:
  420.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  421.                         {
  422.                             default:
  423.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryArcSine]:  "
  424.                                     "bad type"));
  425.                                 break;
  426.                             case eDouble:
  427.                                 Opcode = epOperationDoubleAsin;
  428.                                 break;
  429.                         }
  430.                     break;
  431.  
  432.                 case eUnaryArcCosine:
  433.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  434.                         {
  435.                             default:
  436.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryArcCosine]:  "
  437.                                     "bad type"));
  438.                                 break;
  439.                             case eDouble:
  440.                                 Opcode = epOperationDoubleAcos;
  441.                                 break;
  442.                         }
  443.                     break;
  444.  
  445.                 case eUnaryArcTangent:
  446.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  447.                         {
  448.                             default:
  449.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryArcTangent]:  "
  450.                                     "bad type"));
  451.                                 break;
  452.                             case eDouble:
  453.                                 Opcode = epOperationDoubleAtan;
  454.                                 break;
  455.                         }
  456.                     break;
  457.  
  458.                 case eUnaryLogarithm:
  459.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  460.                         {
  461.                             default:
  462.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryLogarithm]:  "
  463.                                     "bad type"));
  464.                                 break;
  465.                             case eDouble:
  466.                                 Opcode = epOperationDoubleLn;
  467.                                 break;
  468.                         }
  469.                     break;
  470.  
  471.                 case eUnaryExponentiation:
  472.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  473.                         {
  474.                             default:
  475.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryExponentiation]:  "
  476.                                     "bad type"));
  477.                                 break;
  478.                             case eDouble:
  479.                                 Opcode = epOperationDoubleExp;
  480.                                 break;
  481.                         }
  482.                     break;
  483.  
  484.                 case eUnarySquare:
  485.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  486.                         {
  487.                             default:
  488.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnarySquare]:  "
  489.                                     "bad type"));
  490.                                 break;
  491.                             case eDouble:
  492.                                 Opcode = epOperationDoubleSqr;
  493.                                 break;
  494.                         }
  495.                     break;
  496.  
  497.                 case eUnarySquareRoot:
  498.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  499.                         {
  500.                             default:
  501.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnarySquareRoot]:  "
  502.                                     "bad type"));
  503.                                 break;
  504.                             case eDouble:
  505.                                 Opcode = epOperationDoubleSqrt;
  506.                                 break;
  507.                         }
  508.                     break;
  509.  
  510.                 case eUnaryCastToBoolean:
  511.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  512.                         {
  513.                             default:
  514.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryCastToBoolean]:  "
  515.                                     "bad type"));
  516.                                 break;
  517.                             case eBoolean:
  518.                                 Opcode = epNop;
  519.                                 break;
  520.                             case eInteger:
  521.                                 Opcode = epOperationIntegerToBoolean;
  522.                                 break;
  523.                             case eFloat:
  524.                                 Opcode = epOperationFloatToBoolean;
  525.                                 break;
  526.                             case eDouble:
  527.                                 Opcode = epOperationDoubleToBoolean;
  528.                                 break;
  529.                             case eFixed:
  530.                                 Opcode = epOperationFixedToBoolean;
  531.                                 break;
  532.                         }
  533.                     break;
  534.  
  535.                 case eUnaryCastToInteger:
  536.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  537.                         {
  538.                             default:
  539.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryCastToInteger]:  "
  540.                                     "bad type"));
  541.                                 break;
  542.                             case eBoolean:
  543.                                 Opcode = epOperationBooleanToInteger;
  544.                                 break;
  545.                             case eInteger:
  546.                                 Opcode = epNop;
  547.                                 break;
  548.                             case eFloat:
  549.                                 Opcode = epOperationFloatToInteger;
  550.                                 break;
  551.                             case eDouble:
  552.                                 Opcode = epOperationDoubleToInteger;
  553.                                 break;
  554.                             case eFixed:
  555.                                 Opcode = epOperationFixedToInteger;
  556.                                 break;
  557.                         }
  558.                     break;
  559.  
  560.                 case eUnaryCastToSingle:
  561.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  562.                         {
  563.                             default:
  564.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryCastToSingle]:  "
  565.                                     "bad type"));
  566.                                 break;
  567.                             case eBoolean:
  568.                                 Opcode = epOperationBooleanToFloat;
  569.                                 break;
  570.                             case eInteger:
  571.                                 Opcode = epOperationIntegerToFloat;
  572.                                 break;
  573.                             case eFloat:
  574.                                 Opcode = epNop;
  575.                                 break;
  576.                             case eDouble:
  577.                                 Opcode = epOperationDoubleToFloat;
  578.                                 break;
  579.                             case eFixed:
  580.                                 Opcode = epOperationFixedToFloat;
  581.                                 break;
  582.                         }
  583.                     break;
  584.  
  585.                 case eUnaryCastToDouble:
  586.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  587.                         {
  588.                             default:
  589.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryCastToDouble]:  "
  590.                                     "bad type"));
  591.                                 break;
  592.                             case eBoolean:
  593.                                 Opcode = epOperationBooleanToDouble;
  594.                                 break;
  595.                             case eInteger:
  596.                                 Opcode = epOperationIntegerToDouble;
  597.                                 break;
  598.                             case eFloat:
  599.                                 Opcode = epOperationFloatToDouble;
  600.                                 break;
  601.                             case eDouble:
  602.                                 Opcode = epNop;
  603.                                 break;
  604.                             case eFixed:
  605.                                 Opcode = epOperationFixedToDouble;
  606.                                 break;
  607.                         }
  608.                     break;
  609.  
  610.                 case eUnaryCastToFixed:
  611.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  612.                         {
  613.                             default:
  614.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryCastToFixed]:  "
  615.                                     "bad type"));
  616.                                 break;
  617.                             case eBoolean:
  618.                                 Opcode = epOperationBooleanToFixed;
  619.                                 break;
  620.                             case eInteger:
  621.                                 Opcode = epOperationIntegerToFixed;
  622.                                 break;
  623.                             case eFloat:
  624.                                 Opcode = epOperationFloatToFixed;
  625.                                 break;
  626.                             case eDouble:
  627.                                 Opcode = epOperationDoubleToFixed;
  628.                                 break;
  629.                             case eFixed:
  630.                                 Opcode = epNop;
  631.                                 break;
  632.                         }
  633.                     break;
  634.  
  635.                 case eUnaryAbsoluteValue:
  636.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  637.                         {
  638.                             default:
  639.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryAbsoluteValue]:  "
  640.                                     "bad type"));
  641.                                 break;
  642.                             case eInteger:
  643.                                 Opcode = epOperationIntegerAbs;
  644.                                 break;
  645.                             case eFloat:
  646.                                 Opcode = epOperationFloatAbs;
  647.                                 break;
  648.                             case eDouble:
  649.                                 Opcode = epOperationDoubleAbs;
  650.                                 break;
  651.                             case eFixed:
  652.                                 Opcode = epOperationFixedAbs;
  653.                                 break;
  654.                         }
  655.                     break;
  656.  
  657.                 case eUnaryTestNegative:
  658.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  659.                         {
  660.                             default:
  661.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryTestNegative]:  "
  662.                                     "bad type"));
  663.                                 break;
  664.                             case eInteger:
  665.                                 Opcode = epOperationTestIntegerNegative;
  666.                                 break;
  667.                             case eFloat:
  668.                                 Opcode = epOperationTestFloatNegative;
  669.                                 break;
  670.                             case eDouble:
  671.                                 Opcode = epOperationTestDoubleNegative;
  672.                                 break;
  673.                             case eFixed:
  674.                                 Opcode = epOperationTestFixedNegative;
  675.                                 break;
  676.                         }
  677.                     break;
  678.  
  679.                 case eUnaryGetSign:
  680.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  681.                         {
  682.                             default:
  683.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryGetSign]:  "
  684.                                     "bad type"));
  685.                                 break;
  686.                             case eInteger:
  687.                                 Opcode = epOperationGetSignInteger;
  688.                                 break;
  689.                             case eFloat:
  690.                                 Opcode = epOperationGetSignFloat;
  691.                                 break;
  692.                             case eDouble:
  693.                                 Opcode = epOperationGetSignDouble;
  694.                                 break;
  695.                             case eFixed:
  696.                                 Opcode = epOperationGetSignFixed;
  697.                                 break;
  698.                         }
  699.                     break;
  700.  
  701.                 case eUnaryGetArrayLength:
  702.                     switch (GetExpressionsResultantType(UnaryOperator->Argument))
  703.                         {
  704.                             default:
  705.                                 EXECUTE(PRERR(ForceAbort,"CodeGenUnaryOperator [eUnaryGetArrayLength]:  "
  706.                                     "bad type"));
  707.                                 break;
  708.                             case eArrayOfBoolean:
  709.                                 Opcode = epGetBooleanArraySize;
  710.                                 break;
  711.                             case eArrayOfInteger:
  712.                                 Opcode = epGetIntegerArraySize;
  713.                                 break;
  714.                             case eArrayOfFloat:
  715.                                 Opcode = epGetFloatArraySize;
  716.                                 break;
  717.                             case eArrayOfDouble:
  718.                                 Opcode = epGetDoubleArraySize;
  719.                                 break;
  720.                             case eArrayOfFixed:
  721.                                 Opcode = epGetFixedArraySize;
  722.                                 break;
  723.                         }
  724.                     break;
  725.             }
  726.         if (Opcode != epNop)
  727.             {
  728.                 if (!AddPcodeInstruction(FuncCode,Opcode,NIL))
  729.                     {
  730.                         return False;
  731.                     }
  732.             }
  733.  
  734.         *StackDepthParam = StackDepth;
  735.         return True;
  736.     }
  737.